package comport

import (
	"fmt"
)

type SerialDevice interface {
	// SetCom 设置串口名称
	SetCom(comName string)
	// SetBaud 设置波特率
	SetBaud(baud int)
	// SetDataBits 设置数据位
	SetDataBits(dBit int) error
	// SetStopBits 设置停止位，1，2，15
	SetStopBits(sBit byte) error
	// SetParity 设置奇偶校验，N,O,E
	SetParity(p string) error
	// SetDataSize 设置数据位
	SetDataSize(sizes byte) error
	// Open 打开串口
	Open() error
	// Close 关闭串口
	Close()
	// Write 写入数据
	Write(data []byte) (int, error)
	// OnDataArrival 串口缓存有数据是触发回调
	OnDataArrival(callBack func([]byte))
}

type device struct {
	comPort  string `default:"com1"`
	baud     int    `default:"9600"`
	dataBits int    `default:"1"`
	stopBits byte   `default:"1"`
	dataSize byte   `default:"8"`
	parity   Parity `default:"N"`

	com      *myComPort
	callBack func([]byte)
}

// CreateDevice 创建串口对象
func CreateDevice(com string, baud int) (SerialDevice, error) {
	c := new(device)
	c.baud = baud
	c.comPort = com
	c.parity = ParityNone
	c.dataBits = 8
	c.stopBits = 1
	c.dataSize = 8
	return c, nil
}

func (w *device) SetCom(comName string) {
	w.comPort = comName
}

func (w *device) SetBaud(baud int) {
	w.baud = baud
}

func (w *device) SetDataBits(dBit int) error {
	if dBit < 0 || dBit > 8 {
		return fmt.Errorf("数据位配置错误")
	}
	w.dataBits = dBit
	return nil
}

func (w *device) SetStopBits(sBit byte) error {
	if sBit == 1 || sBit == 2 || sBit == 15 {
		w.stopBits = sBit
		return nil
	}
	return fmt.Errorf("停止位配置错误,支持，1，2，15")
}

func (w *device) SetParity(p string) error {
	if p == "N" {
		w.parity = ParityNone
	} else if p == "O" {
		w.parity = ParityOdd
	} else if p == "E" {
		w.parity = ParityEven
	} else {
		return fmt.Errorf("配置错误，该属性只支持N，O，E")
	}
	return nil
}

func (w *device) SetDataSize(size byte) error {
	if size < 0 || size > 8 {
		return fmt.Errorf("数据位配置错误")
	}
	w.dataSize = size
	return nil
}

func (w *device) Open() error {
	var err error
	com := new(myComPort)
	com.Parity = w.parity
	com.ComName = w.comPort
	com.BaudRate = w.baud
	com.DataBits = w.dataBits
	com.StopBits = w.stopBits
	com.DataSize = w.dataSize
	err = com.Open()
	if err == nil {
		w.com = com
		w.com.OnDataArrival(w.callBack)
	} else {
		w.com = nil
	}
	return err
}

func (w *device) Close() {
	if w.com != nil {
		w.com.Close()
		w.com = nil
	}
}

func (w *device) Write(data []byte) (int, error) {
	if w.com != nil {
		return w.com.Write(data)
	}
	return 0, fmt.Errorf("串口未打卡,串口对象为nil")
}

func (w *device) OnDataArrival(ff func([]byte)) {
	w.callBack = ff
}
